<!DOCTYPE html>
<html>
<head>
	<title></title>
	<script type="text/javascript" src="js/jquery-1.11.3.min.js"></script>
	<script type="text/javascript" src="js/knockoutjs.js"></script>
	<style>
		.planet.rock{background-color:#EECCAA;}
		.planet{padding:0.25rem;border: 1px solid silver;margin-bottom: 0.5rem;font-size: 0.75rem;background-color: #AAEECC;}
	</style>
</head>
<body>
	<h2>Planets</h2>
	<p>
		<label for="">
			<input type="checkbox" data-bind="checked:displayAdvancedOptions">
			Display advanced options
		</label>
	</p>
	<p data-bind='fadeVisible:displayAdvancedOptions'>
		Show:
		<label for=""><input type="radio" name="type" value="all" data-bind="checked:typeToShow">All</label>
		<label for=""><input type="radio" name="type" value="rock" data-bind="checked:typeToShow">Rocky planets</label>
		<label for=""><input type="radio" name="type" value="gasgiant" data-bind="checked:typeToShow">Gas giants</label>
	</p>
	<div data-bind='template:{ foreach:planetsToShow,
							   beforeRemove:hidePlanetElement,
							   afterAdd:showPlanetElement
							}'>
		<div data-bind='attr:{"class":"planet " + type},text:name'></div>
	</div>
	<p data-bind='fadeVisible:displayAdvancedOptions'>
		<button data-bind='click:addPlanet.bind($data,"rock")'>Add rocky planet</button>
		<button data-bind='click:addPlanet.bind($data,"gasgiant")'>Add gas giant</button>
	</p>
</body>
<script>
	var PlanetsModel = function(){
		    this.planets = ko.observableArray([
		        { name: "Mercury", type: "rock"},
		        { name: "Venus", type: "rock"},
		        { name: "Earth", type: "rock"},
		        { name: "Mars", type: "rock"},
		        { name: "Jupiter", type: "gasgiant"},
		        { name: "Saturn", type: "gasgiant"},
		        { name: "Uranus", type: "gasgiant"},
		        { name: "Neptune", type: "gasgiant"}
		    ]);
		    this.typeToShow = ko.observable("all");
		    this.displayAdvancedOptions = ko.observable(false);

		    this.addPlanet = function(type){
		    	this.planets.push({
		    		name:"New planet",
		    		type :type
		    	});
		    };

		    this.planetsToShow = ko.pureComputed(function(){
		    	var desiredType = this.typeToShow();
		    	if(desiredType == "all") return this.planets();
		    	return ko.utils.arrayFilter(this.planets(),function(planet){
		    		return planet.type == desiredType;
		    	});
		    },this);

		    this.showPlanetElement = function(elem){
		    	if(elem.nodeType === 1) $(elem).hide().slideDown();
		    };
		    this.hidePlanetElement = function(elem){
		    	if(elem.nodeType === 1) $(elem).slideUp(function(){$(elem).remove();});
		    };
	};

	ko.bindingHandlers.fadeVisible ={
		init : function(element,valueAccessor){
			var value = valueAccessor();
			$(element).toggle(ko.unwrap(value));
		},
		update: function(element,valueAccessor){
			var value = valueAccessor();
			ko.unwrap(value) ? $(element).fadeIn() : $(element).fadeOut();
		}
	};
	ko.applyBindings(new PlanetsModel());
</script>
</html>